package com.gitee.wsl.mathematics.vector.vec3

import com.gitee.wsl.mathematics.vector.MutableVector
import com.gitee.wsl.mathematics.vector.MutableVectorD
import com.gitee.wsl.mathematics.vector.MutableVectorF
import com.gitee.wsl.mathematics.vector.vec4.MutableVector4

typealias MutableVec3F = MutableVector3<Float,*>

typealias MutableVec3D = MutableVector3<Double,*>

interface MutableVector3<T:Number,V: Vector3<T, V>>: Vector3<T, V>, MutableVector<T, V> {

    //override val vec2: MutableVector2<T, *>
    //override val vec3: MutableVector3<T, *>
    override val vec4: MutableVector4<T, *>

    //override val xy : MutableVector2<T, *>
    //override val xz : MutableVector2<T, *>
    //override val yz : MutableVector2<T, *>

    override var x
        get() = proxy[0]
        set(value) {
            proxy[0] = value
        }

    override var y
        get() = proxy[1]
        set(value) {
            proxy[1] = value
        }

    override var z
        get() = proxy[2]
        set(value) {
            proxy[2] = value
        }

    override var length
        get() = sqrt(squaredLength)
        set(value) {
            val newVec = normalized * value
            x = newVec.x
            y = newVec.y
            z = newVec.z
        }

    /*override operator fun plusAssign(v: V) {
        x += v.x
        y += v.y
        z += v.z
    }

    override operator fun timesAssign(other: V) {
        x *= other.x
        y *= other.y
        z *= other.z
    }

    override operator fun divAssign(other: V) {
        x /= other.x
        y /= other.y
        z /= other.z
    }

    override fun subtract(other: V) {
        x -= other.x
        y -= other.y
        z -= other.z
    }*/

    /*fun set(x:T,y:T,z:T){
        this.x=x
        this.y=y
        this.z=z
    }*/

    fun set(x:Number,y:Number,z:Number){
        this.x += x
        this.y += y
        this.z += z
    }

    fun set(other: Vector3<T, *>) = set(other.x,other.y,other.z)

    //override fun set(other: V) = set(other.x,other.y,other.z)

    fun add(x:T, y:T, z:T){
        this.x+=x
        this.y+=y
        this.z+=z
    }

    /*override fun scale(factor: T) {
        x *= factor
        y *= factor
        z *= factor
    }*/

    fun scale(xFactor: T, yFactor: T, zFactor: T) {
        x *= xFactor
        y *= yFactor
        z *= zFactor
    }

    fun plusAssignMul(u: Vector3<T, *>, a: T) {
        x += u.x * a
        y += u.y * a
        z += u.z * a
    }

    /*override fun negate() {
        x *= -1f
        y *= -1f
        z *= -1f
    }*/


     fun subtract(other: Vector3<T, *>) {
        x -= other.x
        y -= other.y
        z -= other.z
    }

}

interface MutableVector3F<V: Vector3<Float, V>> : MutableVector3<Float, V>, MutableVectorF<V>{

}

interface MutableVector3D<V: Vector3<Double, V>> :  MutableVector3<Double, V>, MutableVectorD<V>{


}

